import random
import struct

def crc16_modbus(data: bytes) -> int:
    """计算 Modbus CRC16 (多项式 0xA001, 初值 0xFFFF)"""
    crc = 0xFFFF
    for b in data:
        crc ^= b
        for _ in range(8):
            if crc & 0x0001:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc


def build_caz_frame(address=0x0A, func=0x67, voltages=None):
    """
    构建 caz 帧 (含 CRC16)
    address  : 模块地址 (默认 0x0A)
    func     : 功能码   (默认 0x67)
    voltages : 24 个浮点数 (list/tuple)
    return   : bytes（二进制帧）
    """

    if voltages is None:
        voltages = [0.0] * 24
    elif len(voltages) != 24:
        raise ValueError("voltages 必须是 24 个 float")

    # -----------------------------
    # 帧内容部分
    # -----------------------------
    cmd = b'c'           # 指令码
    subcmd = b'a'        # 子指令
    subsubcmd = b'z'     # 子子指令

    # 24 个 float 小端序
    data = struct.pack('<24f', *voltages)

    # 指令码 + 数据段长度
    length = len(cmd + subcmd + subsubcmd + data)

    # 组装：地址 + 功能码 + 长度 + 数据内容
    frame_wo_crc = struct.pack(
        f'<BBB{length}s',
        address,
        func,
        length,
        cmd + subcmd + subsubcmd + data
    )

    # 计算 CRC16
    crc = crc16_modbus(frame_wo_crc)
    crc_bytes = struct.pack('<H', crc)  # 小端序

    # 拼接完整帧
    return frame_wo_crc + crc_bytes


# 随机帧生成
# voltages = [2.0] * 12 + [3.0] * 12
voltages = [round(random.uniform(0.0, 5.0), 3) for _ in range(24)]
frame = build_caz_frame(0x0A, 0x67, voltages)

print("帧长度:", len(frame))
print("十六进制输出:", frame.hex(' ').upper())


